/****************************************************************
 **                                                             *
 ** Nombre: GestorProgramaEducativo.java                        *
 ** Versión: 1.0.0                                              *
 ** Autor: Amado de Jesús Canté Cauich                          *
 ** Creado: 7-feb-2013                                          *
 ** Modificado:                                                 *
 ** Diagrama: GAPI v4.7.1                                       *
 ** Caso de uso: MGPE1, MGPE2, MGPE3                            *
 ****************************************************************/
package Servicios;

import DAO.DAOCarrera;
import DAO.DAOProgramaEducativo;
import Dominio.Carrera;
import Dominio.ProgramaEducativo;
import Dominio.ReticulaAcademica;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * Gestiona los movimientos relativos a los programas educativos en la base de datos.
 * @author amado.cante
 */
public class GestorProgramaEducativo extends HttpServlet {

    /**
     * Procesa las peticiones recibidas por
     * <code>GET</code> y
     * <code>POST</code> del explorador.
     *
     * @param request Petición del servlet.
     * @param response Respuesta del servlet
     * @throws ServletException Si ocurre un problema con el servlet
     * @throws IOException Si ocurre un  problema de lectura/escritura.
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
         String operacion = request.getParameter("action");
       PrintWriter out = response.getWriter();
       System.out.println("operacion:"+operacion); 
       switch (operacion) {
            case "uploadPE":
                this.iniciaProcesoRegistro(request, response);
                break;
            case "editaPE":
                this.actualizaDatosPE(request,response);
                break;
            case "cambiaRetAcad":
                this.cambiaReticula(request,response);
                break;
            case "eliminarPE":
                this.eliminarProgramaEducativo(request, response);
                break;
            default:
                String resp = "El servicio solicitado no existe.";
                out.println(resp);
                break;
        }
    }
        
    /**
     * Verifica la existencia de un programa educativo en la base de datos.
     * @param nombrePrograma El nombre del programa educativo que se desea verificar su existencia.
     * @return True si existe el programa educativo en la base de datos, False en caso contrario.
     * @throws ServletException Si ocurre un problema con el servlet.
     * @throws IOException Si ocurre un problema de lectura/escritura.
     */
    private boolean existePrograma(String nombrePrograma) throws ServletException, IOException{
        DAOProgramaEducativo daoPrograma = new DAOProgramaEducativo();
        boolean existe = daoPrograma.existeProgramaEducativo(nombrePrograma);
        return existe;
    }
    
    /**
     * Determina si un programa educativo se puede editar o no. Esto se realiza 
     * verificando si el programa educativo tiene algún alumno relacionado.
     * @param nombrePrograma El nombre del programa educativo a evaluar.
     * @param claveProgramaEducativo Clave del Prgrama Educativo.
     * @return True si el programa es editable, False en caso contrario.
     * @throws ServletException Si ocurre algún problema con el servlet.
     * @throws IOException Si ocurre algún problema de lectura/escritura.
     */
    private boolean esEditableElProgramaEducativo(String nombrePrograma, int claveProgramaEducativo) throws ServletException, IOException{
        DAOProgramaEducativo daoPrograma = new DAOProgramaEducativo();
        boolean existe = daoPrograma.esEditableElProgramaEducativo(nombrePrograma, claveProgramaEducativo);
        return existe;
    }
    
    /**
     * Inicia el procedimiento de regisro de programa educativo invocando
     * la carga del archivo de retícula académica y pasando el control al método
     * de procesamiento del archivo.
     * @param request Petición del servlet.
     * @param response Respuesta del servlet.
     * @throws ServletException Si ocurre algún problema con el servlet.
     * @throws IOException  Si ocurre algún problema de lectura/escritura.
     */
    private void iniciaProcesoRegistro(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
            String sFichero = getServletContext().getRealPath("/");
            sFichero += "/../../web/ServerFiles/archivoReticula.xls";
            File fichero = new File(sFichero);        
            if (fichero.exists()) {
                if(!fichero.delete()){
                    System.out.println("Existe un archivo de Reticula Academica en el servidor, será eliminado para proceder con el servicio.");
                }else{
                    HashMap<String,String> campos;
                    campos = subirArchivo(request, response);
                    if(campos!=null){
                        campos.put("ruta", sFichero);
                        registrarProgramaEducativo(request,response,campos);
                        fichero.delete();
                    }
                }
            }
            else{
                HashMap<String,String> campos;
                campos = subirArchivo(request, response);
                if(campos!=null){
                    campos.put("ruta", sFichero);
                    registrarProgramaEducativo(request,response,campos);
                    fichero.delete();
                }
            }
        
        
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    /**
     * Carga el archivo de retícula académica recibido en la petición en el servidor de la aplicación
     * para su procesamiento posterior y procesa los demás parámetros recibidos
     * creando un <code>HashMap</code> con el par variable-valor incluyendo la ruta
     * del archivo de retícula que ha sido cargado.
     * @param request Petición del servlet.
     * @param response Respuesta del servlet.
     * @return HashMap conteniendo el par variable-valor de la petición recibida.
     */
    private HashMap<String,String> subirArchivo(HttpServletRequest request, HttpServletResponse response) {
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        HashMap<String,String> variables;
        variables = new HashMap<>();
        if (isMultipart) {
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            try {
                 List items = upload.parseRequest(request);
                 Iterator iterator = items.iterator();
                 boolean stop = false;
                 while (iterator.hasNext() && !stop) {
                      FileItem item = (FileItem) iterator.next();
                         if (!item.isFormField()) {
                             String fileName = "archivoReticula.xls";
                             String root = getServletContext().getRealPath("/");
                             File path = new File(root + "/../../web/ServerFiles");
                             if (!path.exists()) {
                                 path.mkdirs();
                             }
                             File uploadedFile = new File(path + "/" + fileName);
                             item.write(uploadedFile);
                             stop = true;
                             }else{
                                String variable = item.getFieldName();
                                String valor = item.getString();
                                variables.put(variable, valor);
                            }
                         }
                 return variables;
            } catch (FileUploadException e) {
               e.printStackTrace();
            } catch (Exception e) {
               e.printStackTrace();
            }
           }else{
            return null;
        }
        return null;
    }

    /**
     * Procesa el registro del programa educativo en la base de datos; crea una respuesta
     * para ser mostrada al usuario indicando el éxito o fracaso de la operación.
     * @param request Petición del servlet.
     * @param response Respuesta del servlet.
     * @param mapa 
     */
    private void registrarProgramaEducativo(HttpServletRequest request, HttpServletResponse response, HashMap<String,String> mapa) {
        PrintWriter out = null;
        String sFichero = mapa.get("ruta");
        int cveCarrera = Integer.parseInt(mapa.get("optcarreras"));
        String nombrePrograma = mapa.get("nombrePE");
        try{    
            response.setContentType("text/html;charset=UTF-8");
            out = response.getWriter();
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Registro de programa educativo</title>");
            out.println("</head>");
            out.println("<link href=\"css/estilo.css\" rel=\"stylesheet\" type=\"text/css\"/>");
            out.println("<body>");
            out.println("<div class=\"contenedorGeneral\">");
            String respuesta = "<p>No fu&eacute; posible registrar el Programa Educativo debido a un problema con el servicio.</p>";
            DAOProgramaEducativo daoPrograma = new DAOProgramaEducativo();
            System.out.println("->"+nombrePrograma+":"+daoPrograma.existeProgramaEducativo(nombrePrograma));
            if(!daoPrograma.existeProgramaEducativo(nombrePrograma)){
                LectorExcelDeReticulaAcademica lectorReticula = new LectorExcelDeReticulaAcademica();
                ReticulaAcademica reticula = lectorReticula.leerReticulaAcademica(sFichero);
                DAOCarrera daoCarrera = new DAOCarrera();
                Carrera carrera = daoCarrera.buscarCarrera(cveCarrera);
                if(carrera != null && !nombrePrograma.isEmpty() && reticula != null){
                    ProgramaEducativo programa = new ProgramaEducativo(nombrePrograma, carrera, reticula);                
                    if(daoPrograma.registrarProgramaEducativo(programa)){
                        respuesta = "<h3>Programa Educativo registrado con &eacute;xito.</h3>";
                    }
                }else{
                    if(reticula == null){
                        respuesta = "<p>La estructura del archivo recibido no corresponde con la estructura v&aacute;lida de un archivo de retícula acad&eacute;mica.</p>";
                    }
                }
            }else{
                respuesta="<p>No fue posible registrar el Programa Educativo debido a que ya existe otro con el nombre \""+nombrePrograma+"\" en la base de datos.</p>";
            }
            
            out.println(respuesta);
            out.println("<a href=\"PortalAdministrador.jsp\">Regresar</a>");
            out.println("</div>");
            out.println("</body>");
            out.println("</html>");
        }catch(IOException ex) {
            Logger.getLogger(GestorOfertaAcademica.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            out.close();
        }
    }

    /**
     * Procesa la modificación del nombre y carrera del programa educativo,
     * verifica la existencia de otro programa educativo con el mismo nombre que
     * el que se le desea asignar al programa educativo. Crea la respuesta para el usuario.
     * @param request Petición del servlet.
     * @param response Respuesta del servlet.
     * @throws ServletException Si ocurre algún problema con el servlet.
     * @throws IOException si ocurre algún problema de lectura/escritura.
     */
    protected void actualizaDatosPE(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        int clavePE = Integer.parseInt(request.getParameter("clavePE"));
        int claveCarrera=Integer.parseInt(request.getParameter("claveCarrera"));
        String nombrePE=request.getParameter("nombrePE");
        
        if(!this.esEditableElProgramaEducativo(nombrePE, clavePE)){
           out.println("<p>Imposible actualizar los datos, ya existe un programa educativo con el nombre \""+nombrePE+"\" en la base de datos.</p>"); 
        }else{
            try{
                DAOProgramaEducativo daoprograma = new DAOProgramaEducativo();
                boolean successNombre = daoprograma.editarNombrePrograma(clavePE, nombrePE);
                boolean successCarrera = daoprograma.editarCarreraPrograma(clavePE, claveCarrera);
                if(successNombre && successCarrera){
                    out.println("<p>Programa Educativo actualizado con &eacute;xito.</p>");
                }else{
                    out.println("<p>No fue posible guardar los datos.</p>");
                }
            }finally{
                out.close();
            }
        }
    }

    /**
     * Procesa la petición de cambio de retícula académica del programa educativo
     * cargando el archivo de retícula académica en el servidor e invocando al
     * procesamiento del mismo.
     * @param request Petición del servlet.
     * @param response Respuesta del servlet.
     * @throws ServletException Si cocurre algún problema con el servlet.
     * @throws IOException  Si ocurre algún error de lectura/escritura
     */
    private void cambiaReticula(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String sFichero = getServletContext().getRealPath("/");
        sFichero += "/../../web/ServerFiles/archivoReticula.xls";
        File fichero = new File(sFichero);        
        if (fichero.exists()) {
            if(!fichero.delete()){
                System.out.println("Existe un archivo de Reticula Academica en el servidor, será eliminado para proceder con el servicio.");
            }else{
                HashMap<String,String> campos;
                campos = subirArchivo(request, response);
                if(campos!=null){
                    campos.put("ruta", sFichero);
                    cambiaReticulaPE(request,response,campos);
                    fichero.delete();
                }
            }
        }
        else{
            HashMap<String,String> campos;
            campos = subirArchivo(request, response);
            if(campos!=null){
                campos.put("ruta", sFichero);
                cambiaReticulaPE(request,response,campos);
                fichero.delete();
            }
        }
    }

    /**
     * Realiza el cambio de retícula académica del programa educativo procesando
     * el archivo cargado y genera la respuesta de éxito o fracaso para el usuario.
     * @param request Petición del servlet.
     * @param response Respuesta del servlet.
     * @param mapa Parámetros leidos de la petición.
     * @throws ServletException Si ocurre algún problema con el servlet.
     * @throws IOException Si ocurre algún problema de lectura/escritura.
     */
    private void cambiaReticulaPE(HttpServletRequest request, HttpServletResponse response, HashMap<String, String> mapa) 
            throws ServletException, IOException {
        PrintWriter out = null;
        String sFichero = mapa.get("ruta");
        int clavePE = Integer.parseInt(mapa.get("clavePE"));
        try{
            out = response.getWriter();
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Registro de programa educativo</title>");
            out.println("</head>");
            out.println("<link href=\"css/estilo.css\" rel=\"stylesheet\" type=\"text/css\"/>");
            out.println("<body>");
            out.println("<div class=\"contenedorGeneral\">");
            response.setContentType("text/html;charset=UTF-8");
            String respuesta = "<h3>No fu&eacute; posible actualizar la Ret&iacute;cula Acad&eacute;mica del Programa Educativo debido a un problema con el servicio.</h3>";
            
            LectorExcelDeReticulaAcademica lectorReticula = new LectorExcelDeReticulaAcademica();
            ReticulaAcademica reticula = lectorReticula.leerReticulaAcademica(sFichero);
            DAOProgramaEducativo daoprograma = new DAOProgramaEducativo();
            boolean ok = daoprograma.actualizaReticulaAsociada(clavePE, reticula);
            if(ok){
                respuesta="<h3>Ret&iacute;cula Acad&eacute;mica actualizada correctamente</h3>";
            }
            out.println(respuesta);
            out.println("<a href=\"PortalAdministrador.jsp\">Regresar</a>");
            out.println("</div>");
            out.println("</body>");
            out.println("</html>");
        }finally{
            out.close();
        }
    }

    /**
     * Elimina el programa educativo indicado de la base de datos del sistema 
     * y prepara la respuesta para el usuario.
     * @param request Petición del servlet.
     * @param response  Respuesta del servlet.
     */
    private void eliminarProgramaEducativo(HttpServletRequest request, HttpServletResponse response) {
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = null;
        String clavePEEnCadena = request.getParameter("clavePE");
        
        if(clavePEEnCadena != null) {
            try {
                out = response.getWriter();                
                
                int clavePE = Integer.parseInt(clavePEEnCadena);
                        
                DAOProgramaEducativo daoProgramaEducativo = new DAOProgramaEducativo();
                daoProgramaEducativo.eliminarProgramaEducativo(clavePE);
                daoProgramaEducativo.cerrarconexionAProgramas();
                
                out.println("<h3>Programa educativo eliminado exitosamente</h3>");
            } catch (IOException ex) {
                Logger.getLogger(GestorProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
            }finally{
            out.close();
            }
        }
    }

}